//9．巨人航空公司（编程练习8）需要另一架飞机（容量相同），每天飞4班（航班102、311、444和519）。
//把程序扩展为可以处理4个航班。用一个顶层菜单提供航班选择和退出。
//选择一个特定航班，就会出现和编程练习8类似的菜单。
//但是该菜单要添加一个新选项：确认座位分配。而且，菜单中的退出是返回顶层菜单。
//每次显示都要指明当前正在处理的航班号。另外，座位分配显示要指明确认状态。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>


#define FILEPATHLEN 40
#define LEN 14
#define SEATS 12
#define EMPTY 0
#define TAKEN 1
struct planestate {
    int seat_id;
    int status;
    char last[LEN];
    char first[LEN];
};

static void eatline();

static int get_i();

static int get_opt_seat(int min, int max);

char *s_gets(char *st, int n);

//选择菜单
static char choice_menu();

//Show number of empty seats
static void show_empty_seats_number(struct planestate plane[], int size);

//Show list of empty seats
static void show_empty_seats(struct planestate plane[], int size);

//Show alphabetical list of seats（根据姓名排序）
static void show_alphabetical_seats(struct planestate plane[], int size);

//Assign a customer to a seat assignment
static void assignment(struct planestate *plan);

//选择航班中的座位
void seat_choose(int fltno);

char top_menu();

int main(void) {
    char sel;
    while ((sel = top_menu()) != 'e') {
        switch (sel) {
            case 'a':
                seat_choose(102);
                break;
            case 'b':
                seat_choose(311);
                break;
            case 'c':
                seat_choose(444);
                break;
            case 'd':
                seat_choose(519);
                break;
        }

    }
}

char top_menu() {
    const int st_size = 10;
    char st[st_size];
    //是否是a-e
    puts("To choose a flight number, enter its letter label:\n"
         "a) 102\tb) 311\n"
         "c) 444\td) 519\n"
         "e) Quit\n");
    char chs[] = "a|b|c|d|e";
    while (s_gets(st, st_size) == NULL || strchr(chs, st[0]) == NULL) {
        printf("输入a|b|c|d|e|\n");
    }
    return st[0];
}

void seat_choose(int fltno) {
    //获取文件路径
    char filepath[FILEPATHLEN] = "../unit14/plane";
    sprintf(filepath, "../unit14/plane%d.dat", fltno);
    FILE *fp;
    char choice;
    int seat_id;
    size_t planestate_size = sizeof(struct planestate);
    size_t size = (size_t) SEATS;
    struct planestate plane[SEATS];

    //读取文件中的数据
    if ((fp = fopen(filepath, "rb")) == NULL) {
        for (int i = 0; i < SEATS; ++i) {
            plane[i] = (struct planestate) {
                    .seat_id=i + 1,
                    .status=EMPTY,
                    .last="",
                    .first=""
            };
        }
    } else {
        fread(plane, planestate_size, size, fp);
        fclose(fp);
    }
    printf("Current flight number:%d\n", fltno);
    while ((choice = choice_menu()) != 'g') {
        switch (choice) {
            case 'a':
                show_empty_seats_number(plane, SEATS);
                break;
            case 'b':
                show_empty_seats(plane, SEATS);
                break;
            case 'c':
                show_alphabetical_seats(plane, SEATS);
                break;
            case 'd':
                seat_id = get_opt_seat(1, SEATS);
                assignment(&plane[seat_id - 1]);
                break;
            case 'e':
                seat_id = get_opt_seat(1, SEATS);
                plane[seat_id - 1].status = EMPTY;
                plane[seat_id - 1].last[0] = '\0';
                plane[seat_id - 1].first[0] = '\0';
                break;
            case 'f':
                //保存内存中的数据
                if ((fp = fopen(filepath, "wb")) != NULL) {
                    fwrite(plane, planestate_size, size, fp);
                    fclose(fp);
                } else {
                    fputs("Save failed,Can't open file.\n", stderr);
                    exit(EXIT_FAILURE);
                }
                break;
        }
    }
}

static char choice_menu() {
    const int st_size = 10;
    char st[st_size];
    //是否是a-e
    puts("To choose a function, enter its letter label:\n"
         "a) Show number of empty seats\n"
         "b) Show list of empty seats\n"
         "c) Show alphabetical list of seats\n"
         "d) Assign a customer to a seat assignment\n"
         "e) Delete a seat assignment\n"
         "f) Sure seat assignment\n"
         "g) Quit");
    char chs[] = "a|b|c|d|e|f|g";
    while (s_gets(st, st_size) == NULL || strchr(chs, st[0]) == NULL) {
        printf("输入a|b|c|d|e|f|g\n");
    }
    return st[0];
}

static void show_empty_seats_number(struct planestate plane[], int size) {
    printf("number of empty seats:");
    int sum = 0;
    for (int i = 0; i < size; ++i) {
        if (plane[i].status == EMPTY) {
            sum++;
        }
    }
    printf("%d\n", sum);
}

static void show_empty_seats(struct planestate plane[], int size) {
    printf("list of empty seats:");
    int sum = 0;
    for (int i = 0; i < size; ++i) {
        if (plane[i].status == EMPTY) {
            sum++;
            printf(" %d", plane[i].seat_id);
        }
    }
    if (sum == 0) {
        printf(" none\n");
        printf("full of seats");
    }
    puts("");
}

//Show alphabetical list of seats（根据姓名排序）
static void show_alphabetical_seats(struct planestate plane[], int size) {
    struct planestate p1[size];
    int sum = 0;
    for (int i = 0; i < size; ++i) {
        if (plane[i].status == TAKEN) {
            p1[sum] = plane[i];
            sum++;
        }
    }
    for (int i = 0; i < sum - 1; ++i) {
        for (int j = i + 1; j < sum; ++j) {
            if (strncmp(p1[i].first, p1[j].first, LEN) > 0) {
                struct planestate temp = p1[i];
                p1[i] = p1[j];
                p1[j] = temp;
            }
        }
    }
    if (sum == 0) {
        fputs("alphabetical list of seats:", stdout);
        puts("没有人预定座位.");
    } else {
        puts("alphabetical list of seats:");
    }
    for (int k = 0; k < sum; ++k) {
        printf("%d:%s,%s\n", p1[k].seat_id, p1[k].first, p1[k].last);
    }
}

static void assignment(struct planestate *plan) {
    printf("Enter your full name:");
    while (scanf("%s%s", plan->first, plan->last) != 2) {
        fputs("Enter your full name(eg:孔明 诸葛):", stderr);
        eatline();
    }
    plan->status = TAKEN;
    eatline();
}

char *s_gets(char *st, int n) {
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val) {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

static void eatline() {
    while (getchar() != '\n')
        continue;/* clear input line  */
}

static int get_i() {
    int i;
    int s = scanf("%d", &i);
    eatline();
    if (s != 1)return 0;
    return i;
}

static int get_opt_seat(int min, int max) {
    printf("输入你要操作的座位号(%d-%d):", min, max);
    int i;
    for (i = get_i(); i < min || i > max; i = get_i()) {
        printf("只能输入%d-%d:", min, max);
    }
    return i;
}

